package pl.com.qapps.datastore;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

/**
 * @author Jakub Dykowski
 * 
 */
public interface TransactionStack {
	/**
	 * Pushes the provided transaction.
	 * 
	 * @param txn
	 *            The transaction to push.
	 */
	void push(Transaction txn);

	/**
	 * Removes the provided transaction. The transaction can be at any location
	 * on the stack.
	 * 
	 * @param txn
	 *            The transaction to remove.
	 * @throws IllegalStateException
	 *             If the provided transaction was not on the stack at any
	 *             location.
	 */
	void remove(Transaction txn);

	/**
	 * Returns the current transaction, or throws an exception if there is no
	 * current transaction.
	 * 
	 * @return The current transaction.
	 * @throws IllegalStateException
	 *             If there is no current transaction.
	 */
	Transaction peek();

	/**
	 * Returns the current transaction, or returns the parameter if there is no
	 * current transaction.
	 * 
	 * @param returnedIfNoTxn
	 *            The return value of this method if there is no current
	 *            transaction.
	 * @return The current transaction, or the parameter that was passed in if
	 *         there is no current transaction.
	 */
	Transaction peek(Transaction returnedIfNoTxn);

	/**
	 * @return All {@link Transaction}s started by this thread upon which no
	 *         attempt to commit or rollback has been made.
	 */
	Collection<Transaction> getAll();

	/**
	 * Clear the stack
	 */
	void clearAll();

	/**
	 * Associate the provided {@link Future} with the provided
	 * {@link Transaction} so that we can block on the Future's completion when
	 * the txn is committed or rolled back.
	 */
	void addFuture(Transaction txn, Future<?> future);

	/**
	 * Returns the {@link Future Futures} associated with the provided
	 * {@link Transaction}.
	 */
	Set<Future<?>> getFutures(Transaction txn);

	/**
	 * Register that the provided entities were put as part of the given txn.
	 */
	void addPutEntities(Transaction txn, List<Entity> putEntities);

	/**
	 * Returns the entities that were put as part of the given txn.
	 */
	List<Entity> getPutEntities(Transaction txn);

	/**
	 * Register that the entities uniquely identified by the given keys were
	 * deleted as part of the given txn.
	 */
	void addDeletedKeys(Transaction txn, List<Key> deletedKeys);

	/**
	 * Returns the keys uniquely identifying the entities that were deleted as
	 * part of the given txn.
	 */
	List<Key> getDeletedKeys(Transaction txn);
}
